// maze.h: Header for Maze abstract class.
// Written by Victor Luna Freire - victorclf@live.com
// Copyright (c) Victor Luna Freire. All rights reserved.
// Monday, October 26, 2009 12:48:08 AM

#ifndef MAZE_H_8713871298371298738
#define MAZE_H_8713871298371298738

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

#include "shared.h"

/*
 * WARNING: 
 * All maze arrays follow the mathematical matrix notation: (line, column)
 * Examples: array[height][width], array[y][x], ... 
 *
 * This is in order to allow easier hardcoding and visualization for *testing* purposes and also to mantain 
 * compatibility with AX's engine.
 */

// Abstract class representing a maze that is processed.
class Maze {
protected:
	// Wall identifiers
	static const char NO_WALL, 
					  WALL;

	int w,
		h;

	std::vector<std::string> maze; // maze's true representation (ready to be rendered)
	

	// Coordinate manipulation 
	
	// Return the true(export format) representation coordinates of a cell.
	Vec2i true_coords(const Vec2i &pos) const { return Vec2i(pos.x * 2 + 1, pos.y * 2 + 1); };
	// Are the true coordinates passed valid?
	bool valid_true_coords(const Vec2i &pos) const { return (0 <= pos.x && pos.x < (int) maze[0].size()) && (0 <= pos.y && pos.y < (int) maze.size()); };
	// Get adjacent positions from a given position. (position == cell in true representation)
	std::vector<Vec2i> get_adjacent_pos(const Vec2i &pos) const;

	
	// Cell coordinates are for representing a maze without its walls.
	// Return the cell coordinates from a numbered vertex.
	Vec2i cell_coords(int vertex) const { return Vec2i(vertex % w , vertex / w); };
	// Are the cell coordinates passed valid?
	bool valid_cell_coords(const Vec2i &pos) const { return (0 <= pos.x && pos.x < w) && (0 <= pos.y && pos.y < h); };
	// Get adjacent cells from cell maze.
	std::vector<Vec2i> get_adjacent_cells(const Vec2i &cell) const;

public:
	// Construct Maze of width and height.
	Maze::Maze(int width, int height) : w(width), h(height) { };

	// Construct Maze using a maze's true representation
	Maze::Maze(std::vector<std::string> new_maze)
		: maze(new_maze),
		  w((new_maze[0].size() - 1) / 2), 
		  h((new_maze.size() - 1) / 2) { };
	
	// Perform next step in the maze processing. Returns false if the processing is over. Starts processing if it was not started before.
	virtual bool next_step() = 0;
	// Finish processing, process all steps. Returns false if the processing is over.
	bool all_steps();
	// Is the process done?
	virtual bool is_done() const = 0;


	// Accessor methods
	int width() const { return w; };
	int height() const { return h; };
	int true_width() const { return w * 2 + 1; };
	int true_height() const { return h * 2 + 1; };
	// HACK: should return a reference and use Boost.Python call policy facilities
	std::vector<std::string> get_maze() const { return maze; };

	friend std::ostream& operator<<(std::ostream& ost, const Maze& m);
};


#endif // MAZE_H_8713871298371298738